package lab.dexter.bbsreader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.SyncBasicHttpContext;


public class NewSMTHHttpClient {
	
	static private NewSMTHHttpClient smthClient;
	
	static public NewSMTHHttpClient getClient() {
		if(smthClient == null) {
			smthClient = new NewSMTHHttpClient();
		}
		return smthClient;
	}
	
	private HttpClient client;
	private HttpContext context;
	
	
	private final String LOGIN_TARGET = "http://www.newsmth.net/bbslogin.php?mainurl=atomic2.php";
	private final String LOGOUT_TARGET = "http://www.newsmth.net/atomic2.php?act=logout";
	//private final String HOST_NAME = "http://www.newsmth.net";
	
	private final String FIELD_ID = "id";
	private final String FIELD_PASSWD = "passwd";
	
	// user id in the cookie
	private final String COOKIE_ID = "UTMPUSERID";
	
	// this is the agent string of Nexus One
	private final String USER_AGENT = "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/ FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1";
	
	private NewSMTHHttpClient() {
		client = new DefaultHttpClient();
		context = new SyncBasicHttpContext(new BasicHttpContext());
		// keep the cookie stored in the context, may need a new cookie store impl
		context.setAttribute(ClientContext.COOKIE_STORE, new BasicCookieStore());
		// hide the default HttpClient agent, otherwise the server will kick you out
		HttpProtocolParams.setUserAgent(client.getParams(), USER_AGENT);
		client.getParams().setBooleanParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
	}
	
	private boolean validate(String id) throws IOException {
		HttpGet get = new HttpGet("http://www.newsmth.net/atomic2.php");
		HttpResponse response = client.execute(get, context);
		HttpEntity entity = response.getEntity();
		entity.consumeContent();
		
		CookieStore store = (CookieStore) context.getAttribute(ClientContext.COOKIE_STORE);
		List<Cookie> cookies = store.getCookies();
		for (Iterator<Cookie> it = cookies.iterator(); it.hasNext();) {
			Cookie cookie = it.next();
			//System.out.println(cookie.getName() + "=" + cookie.getValue());
			//Log.v("COOKIE", cookie.getName() + "=" + cookie.getValue());
			if(cookie.getName().equalsIgnoreCase(COOKIE_ID)) {
				if(cookie.getValue().equalsIgnoreCase(id)) {
					return true;
				}
				if(!cookie.getValue().equalsIgnoreCase("guest")) {
					logout();
					return false;
				}
			}
		}
		return false;
	}
	
	public boolean login(String id, String passwd) throws IOException {
		// if already logged in, return directly
		if(validate(id)) {
			return true;
		}
		
		HttpPost post = new HttpPost(LOGIN_TARGET);
		// the right way to set content of the request
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		params.add(new BasicNameValuePair(FIELD_ID, id));
		params.add(new BasicNameValuePair(FIELD_PASSWD, passwd));
		post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
		
		// I don't think they really check this, but it does no harm
		post.addHeader("Referer", "http://www.newsmth.net/atomic2.php");
		
		HttpResponse response = client.execute(post, context);
		////// For debug only
		//Header[] headers = response.getAllHeaders();
		//for (int i = 0; i < headers.length; i++) {
			//System.out.println(headers[i].getName() + ":" + headers[i].getValue());
		//	Log.v("HEADER", headers[i].getName() + ":" + headers[i].getValue());
		//}
		/////////////		
		
		HttpEntity entity = response.getEntity();
		entity.consumeContent();
		//System.out.println(EntityUtils.toString(entity, "GB2312"));
		
		CookieStore store = (CookieStore) context.getAttribute(ClientContext.COOKIE_STORE);
		List<Cookie> cookies = store.getCookies();
		for (Iterator<Cookie> it = cookies.iterator(); it.hasNext();) {
			Cookie cookie = it.next();
			//System.out.println(cookie.getName() + "=" + cookie.getValue());
			//Log.v("COOKIE", cookie.getName() + "=" + cookie.getValue());
			if(cookie.getName().equalsIgnoreCase(COOKIE_ID)) {
				return true; 
			}
		}
		return false;
	}
	
	public boolean isLoggedIn(String username) {
		CookieStore store = (CookieStore) context.getAttribute(ClientContext.COOKIE_STORE);
		if(store != null) {
			List<Cookie> cookies = store.getCookies();
			for (Iterator<Cookie> it = cookies.iterator(); it.hasNext();) {
				Cookie cookie = it.next();
				//System.out.println(cookie.getName() + "=" + cookie.getValue());
				//Log.v("COOKIE", cookie.getName() + "=" + cookie.getValue());
				if(cookie.getName().equalsIgnoreCase(COOKIE_ID)) {
					return cookie.getValue().equalsIgnoreCase(username);
				}
			}
		}
		return false;
	}
	
	public String getLoggedInID() {
		CookieStore store = (CookieStore) context.getAttribute(ClientContext.COOKIE_STORE);
		if(store != null) {
			List<Cookie> cookies = store.getCookies();
			for (Iterator<Cookie> it = cookies.iterator(); it.hasNext();) {
				Cookie cookie = it.next();
				//System.out.println(cookie.getName() + "=" + cookie.getValue());
				//	Log.v("COOKIE", cookie.getName() + "=" + cookie.getValue());
				if(cookie.getName().equalsIgnoreCase(COOKIE_ID)) {
					return cookie.getValue();
				}
			}
		}
		return null;
	}
	
	public void logout() {
		try {
			HttpGet get = new HttpGet(LOGOUT_TARGET);
			HttpResponse response = client.execute(get, context);
			HttpEntity entity = response.getEntity();
			entity.consumeContent();
		} catch (IOException e) {
			// do nothing
		}
	}
	
	public void fetchData(String url, DataHandler handler) throws IOException {
		HttpGet get = new HttpGet(url);
		HttpResponse response = client.execute(get, context);
		
//		Header[] headers = response.getAllHeaders();
//		for (int i = 0; i < headers.length; i++) {
//			//System.out.println(headers[i].getName() + ":" + headers[i].getValue());
//			Log.v("HEADER", headers[i].getName() + ":" + headers[i].getValue());
//		}
		
		HttpEntity entity = response.getEntity();
		handler.dataProcessor(entity);
		entity.consumeContent();
	}
}